package transaction

import (
	"bytes"
	"crypto/sha256"
	"encoding/gob" // 用于结构体序列化
	"goblockchain/constcoe"
	"goblockchain/utils" // 自定义工具包，一般用于错误处理等
)

// Transaction 表示一笔交易，包含交易 ID、输入和输出
type Transaction struct {
	ID      []byte     // 交易 ID，是该交易内容的哈希值
	Inputs  []TxInput  // 输入数组（引用以前交易输出）
	Outputs []TxOutput // 输出数组（给哪些地址转了多少钱）
}

// TxHash 计算当前交易的哈希值（即交易 ID）
// 哈希值是对整个交易序列化后求 sha256，保证内容唯一性和不可篡改
func (tx *Transaction) TxHash() []byte {
	var encoded bytes.Buffer // 存储序列化后的交易数据
	var hash [32]byte        // 存储计算出的哈希结果

	// 使用 gob 对交易结构体进行序列化（编码）
	encoder := gob.NewEncoder(&encoded)
	err := encoder.Encode(tx)     // 将 tx 编码写入 encoded 缓冲区
	utils.Handle(err)             // 错误统一处理函数（例如 panic）

	// 对序列化后的字节进行 SHA-256 哈希
	hash = sha256.Sum256(encoded.Bytes())

	// 返回 hash 的切片（[:] 从数组变成切片）
	return hash[:]
}

func (tx *Transaction) SetID() {
	tx.ID = tx.TxHash()
}

// tx in gensis-block, mine init-coin for the god alan
func BaseTx(ToAddress []byte) *Transaction{
	txIn := TxInput{
		TxId: []byte{},
		OutIdx: -1,
		FromAddress: []byte{},
	}
	txOut := TxOutput{
		Value: constcoe.InitCoin,
		ToAddress: ToAddress,
	}
	tx := &Transaction{
		ID: []byte("This is base tx!"),
		Inputs: []TxInput{txIn},
		Outputs: []TxOutput{txOut},
	}
	return tx
}

func (tx *Transaction) IsBase()bool{
	return len(tx.Inputs) == 1 && tx.Inputs[0].OutIdx == -1
}